class BlackDeathEnemyController extends AIController;
var Actor target;//A local varible for things to smash throught to get to our enemy
var vector nextDestinationVector;
var BlackDeathPawn BDP;
var int MaxPerceptionRange, i;
var float r;


auto state Idle
{
//Plays when an enemy is not currently looking at anything 
Begin:
	//`log("Zombie idle");
	Enemy = None;
	While(!Search())//Continuous force the enemy to try and lock onto the player
	{
		//`log("I didn't see anyone");
		//play some idel animation stuff?
		r = RandRange(0.0, 1.0);
		//`log("R: "@r);
		if(r > 0.9)
		{
			//`log("Wondering");
			if(Wander())
			MoveTo(NextDestinationVector);
		}
		else
		{
			//`log("sleeping");
			sleep(0.2);
		}
	}
	goToState('pursuing');//We should chase him now
}

state Faceing
{
Begin:
	nextDestinationVector = Normal(Enemy.Location-Pawn.location);//The normalized direction to our enemy
	r = nextDestinationVector dot Vector(Pawn.rotation);
	while(r > 0.9)
	{
		SetRotation(Pawn.Rotation);
	}
	goToState('pursuing');
}

state pursuing
{
//Plays when an enemy is chaseing someone
Begin:
	//Build path
	//While we haven't reached the target, follow: add some code to allow enemies to know how to break down wall
	//When we reached him, go to next state
	//`log("chaseing something");
	while(pawn != none && enemy != none)
	{	
		if(vsize(Enemy.location-Pawn.location) > Pawn.Weapon.WeaponRange)
		{
			//`log("VSize: "@vsize(Enemy.location-Pawn.location));
			//`log("Pawn?"@Pawn@"  &&  "@"Not there yet?"@!Pawn.ReachedDestination(Enemy));
			//`log("Enemy"@Enemy);
			//MoveTo(GeneratePathToActor(Enemy),none,30,false);
			
			//CurrentTargetIsReachable = NavActorReachable(Enemy);
			//`log("Reachable"@NavActorReachable(Enemy));
			if(!NavActorReachable(Enemy))
			{
				//WorldInfo.Game.Broadcast(None, "Indirect Path");
				Focus = none;
				nextDestinationVector = GeneratePathToActor(Enemy);
				//`log("!NavActorReachable"@nextDestinationVector);
				//MoveToward(Enemy,Enemy);
				//`log("Actor not reachable, sleep");
				Sleep(0.5);				
			}
			else
			{
				//WorldInfo.Game.Broadcast(None, "Direct Path");
				Focus = Enemy;
				nextDestinationVector = Enemy.Location;
				//`log("NavActorReachable"@Enemy@Enemy.Location);
				MoveToward(Enemy);
			}
		}
		else
		{
			//WorldInfo.Game.Broadcast(None, "Destination reached");
			gotostate('attacking');
		}
	}
	gotostate('Idle');
}

state attacking
{
//Plays when an enemy is attacking something
		
		
Begin:
	//while we are within range, attack
	//if we lose him, go back to purseuing
	`log("Zombie attack");
	
	BDP = BlackDeathPawn(Pawn);
	while(Enemy != none && vsize(Pawn.Location-Enemy.Location) <= Pawn.Weapon.WeaponRange)//If we're within range
	{
		if(Pawn.CanAttack(Enemy))
		{
			Pawn.BotFire(true);//fire all guns! Unlease HELL!!
			sleep(0.1);//wait for attack anim to end
		}
	}
	StopFiring();
	if(enemy == none)
	{
		gotostate('idle');
	}
	gotostate('pursuing');
	//`log("going to pursue");
}

simulated function InitNavigationHandle()
{
	if( NavigationHandleClass != None && NavigationHandle == none )
		NavigationHandle = new(self) NavigationHandleClass;
}

function bool NavActorReachable(Actor a)
{
	local bool retValue;

	if ( NavigationHandle == None )
		InitNavigationHandle();

	retValue = NavigationHandle.ActorReachable(a);
	
	//if(retValue)
	//	ClearTimer('NoPathDeathTimer');

	return retValue;
}

event vector GeneratePathToActor( Actor Goal, optional float WithinDistance, optional bool bAllowPartialPath )
{
	local vector NextDest;
	NextDest = Pawn.Location;

	if ( NavigationHandle == None )
	{
		InitNavigationHandle();
	}

	if(!NavActorReachable(Goal))
	{
		class'NavMeshPath_Toward'.static.TowardGoal( NavigationHandle, Goal );
		class'NavMeshGoal_At'.static.AtActor( NavigationHandle, Goal, WithinDistance, true );
		if ( NavigationHandle.FindPath() )
		{
			//WorldInfo.Game.Broadcast(None, "Next destination");
			//ClearTimer('NoPathDeathTimer');
			NavigationHandle.GetNextMoveLocation(NextDest, 60);
		}
		else
		{
			// abort the move
			//Worldinfo.Game.Broadcast(self, "Failed to find path to"@Goal);
			ForceTargetPlayer();
		}
	}

	NavigationHandle.ClearConstraints();

	return NextDest;
}

function bool Search()
{
	//get all the heros within your perception range
	local Vector V, PawnV;
	local float dot, dist;
	ForEach CollidingActors(class'BlackDeathPawn', BDP, MaxPerceptionRange, Pawn.Location)
	{
		if(BDP != Pawn)//ignore your own pawn
		{
			if(BlackDeathHeroPawn(BDP) != none && BDP.Health >0)//if its a hero, which is an enemy
			{
				V = BDP.location;//get the new pawn's location
				V.Z = 0;//ignore z for now
				PawnV = Pawn.location;//our location
				PawnV.Z = 0;//ignore Z again
				Dot = Normal(V-PawnV) dot Vector(Pawn.rotation);//Take the direction of the line from me to you and dot it with my rotation (returns a number between -1 and 1, 1 for faceing dead on, -1 for dead away and 0 for a 90 degree angle).
				Dist = VSize(V-PawnV);//The distance between the pawns
				//`log(dot);
				//`log(dist);
				if(Dot > 0.5&&Dist <= 300)//if within a 90 degree cone of vision
				{
					enemy = BDP;
					return true;
				}
				if(Dot > 0&&Dist <= 200)//within a 180 degree view cone
				{
					enemy = BDP;
					return true;
				}
				if(Dist <= 100)//if behind
				{
					enemy = BDP;
					return true;
				}
			}
		}
	}
	return false;
	
}

function bool ForceTargetPlayer()//Force the AI to target the player, useful for when we don't want to wait for a zombie to spot Vincient
{//Returns true if a target was found, else false
	local BlackDeathHeroPawn Player;
	foreach WorldInfo.AllPawns(class'BlackDeathHeroPawn',Player)
	{
		if(Player != none && Player.Controller != none)
		{
			if(Player.Controller.bIsPlayer)
			{
				enemy = Player;
				return true;
			}
		}
	}
	enemy = none;
	//`warn("no player was found to force target!");
	return false;
}

function bool Wander()
{
	local Vector V;
	if ( NavigationHandle == None )
	{
		InitNavigationHandle();
	}
	V = Pawn.location;
	V.x += RandRange(-50.0, 50.0);
	V.y += RandRange(-50.0, 50.0);
	if(NavigationHandle.PointReachable(V))
	{
		nextDestinationVector = V;
		return true;
	}
	return false;
}

function CancelTarget()
{
	enemy = none;
}

DefaultProperties
{
	bUsingPathLanes=true
	MaxPerceptionRange = 1000
	bIsPlayer=true
}